package org.deltaset.secured.upload;

import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.Serializable;
import javax.imageio.ImageIO;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.PrePersist;
import javax.persistence.Version;
import org.deltaset.meta.annotation.DsCustom;
import org.deltaset.secured.user.EmbeddedFile;

/**
 *
 * @author dmakariev
 */
@Entity
public class MultipleFile implements Serializable {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Version
    @Column(name = "version", nullable = false, updatable = false, unique = false)
    private Long version;
    @DsCustom("richtext")
    private String note;
    @Embedded
    private EmbeddedFile embeddedFile;
    @Embedded
    @AttributeOverrides({
        @AttributeOverride(column =
        @Column(name = "f_name"), name = "name"),
        @AttributeOverride(column =
        @Column(name = "f_contentType"), name = "contentType"),
        @AttributeOverride(column =
        @Column(name = "f_fileSize"), name = "fileSize"),
        @AttributeOverride(column =
        @Column(name = "f_content"), name = "content")
    })
    private EmbeddedFile firstFile;
    @Embedded
    @AttributeOverrides({
        @AttributeOverride(column =
        @Column(name = "s_name"), name = "name"),
        @AttributeOverride(column =
        @Column(name = "s_contentType"), name = "contentType"),
        @AttributeOverride(column =
        @Column(name = "s_fileSize"), name = "fileSize"),
        @AttributeOverride(column =
        @Column(name = "s_content"), name = "content")
    })
    private EmbeddedFile secondFile;
    
    public String title() {
        return this.getEmbeddedFile().getName();
    }
    
    public EmbeddedFile getEmbeddedFile() {
        if (null == embeddedFile) {
            embeddedFile = new EmbeddedFile();
        }
        return embeddedFile;
    }
    
    @PrePersist
    private void prePersist() {
        final long startTime = System.currentTimeMillis();
        
        this.setSecondFile(resizeTo200x200(this.embeddedFile));
        this.setFirstFile(resizeTo100x100(this.getSecondFile()));
        System.out.println(" resized for " + (System.currentTimeMillis() - startTime) + "ms");
    }

    //XXX:is setEmbeddedFile ever called ??
    public void setEmbeddedFile(EmbeddedFile embeddedFile) {
        this.embeddedFile = embeddedFile;        
    }
    
    public EmbeddedFile getFirstFile() {
        if (null == firstFile) {
            firstFile = new EmbeddedFile();
        }
        return firstFile;
    }
    
    public void setFirstFile(EmbeddedFile firstFile) {
        this.firstFile = firstFile;
    }
    
    public EmbeddedFile getSecondFile() {
        if (null == secondFile) {
            secondFile = new EmbeddedFile();
        }
        return secondFile;
    }
    
    public void setSecondFile(EmbeddedFile secondFile) {        
        this.secondFile = secondFile;
    }
    
    public String getNote() {
        return note;
    }
    
    public void setNote(String note) {
        this.note = note;
    }
    
    private static EmbeddedFile resizeTo100x100(EmbeddedFile original) {
        final EmbeddedFile resized = resizeTo(original, 100, 100);
        return resized;
    }
    
    private static EmbeddedFile resizeTo200x200(EmbeddedFile original) {
        final EmbeddedFile resized = resizeTo(original, 200, 200);
        return resized;
    }
    
    private static EmbeddedFile resizeTo(
            final EmbeddedFile embeddedFile,
            final int scaledWidth,
            final int scaledHeight) {
        try {
            final InputStream is = new ByteArrayInputStream(embeddedFile.getContent());
            final BufferedImage bufferedImage = ImageIO.read(is);
            
            final BufferedImage resizedImage = createResizedCopy(bufferedImage, scaledWidth, scaledHeight, true);
            
            final ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ImageIO.write(resizedImage, "png", bos);
            
            final byte[] newContent = bos.toByteArray();            
            
            final EmbeddedFile resizedEmbeddedFile = new EmbeddedFile(embeddedFile, newContent);
            resizedEmbeddedFile.setContentType("image/png");
            return resizedEmbeddedFile;
            
        } catch (Exception ex) {
        }
        return null;
    }
    
    private static BufferedImage createResizedCopy(
            final Image originalImage,
            final int scaledWidth,
            final int scaledHeight,
            final boolean preserveAlpha) {
        // System.out.println("resizing...");
        final int imageType = preserveAlpha ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
        final BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType);
        final Graphics2D g = scaledBI.createGraphics();
        if (preserveAlpha) {
            g.setComposite(AlphaComposite.Src);
        }
        g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null);
        g.dispose();
        return scaledBI;
    }
}
